﻿using Onshi.POS.Modelo.Entidades;
using Onshi.POS.Modelo.Enumeradores;
using Onshi.POS.Repositorios;
using Onshi.POS.Proveedores.Vistas;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Text;
using Onshi.POS.Modelo.Objectos;

namespace Onshi.POS.Proveedores
{
    public class ProveedoresAltaModificacionPresentador
    {
        #region Constructores

        public ProveedoresAltaModificacionPresentador(IProveedoresAltaModificacion vista)
        {
            this.vista = vista;
        }

        #endregion

        #region Atributos

        private IProveedoresAltaModificacion vista;

        #endregion

        #region Propiedades

        private RepositorioCamposPersonalizadosProveedores RepositorioCamposPersonalizadosProveedores
        {
            get { return new RepositorioCamposPersonalizadosProveedores(); }
        }

        private RepositorioEventos RepositorioEventos
        {
            get { return new RepositorioEventos(); }
        }

        private RepositorioListasPreciosCompras RepositorioListasPreciosCompras
        {
            get { return new RepositorioListasPreciosCompras(); }
        }

        private RepositorioProveedores RepositorioProveedores
        {
            get { return new RepositorioProveedores(); }
        }

        private RepositorioRubrosProveedores RepositorioRubrosProveedores
        {
            get { return new RepositorioRubrosProveedores(); }
        }

        private RepositorioTiposIvas RepositorioTiposIvas
        {
            get { return new RepositorioTiposIvas(); }
        }

        private RepositorioTiposDomicilios RepositorioTiposDomicilios
        {
            get { return new RepositorioTiposDomicilios(); }
        }

        private RepositorioTiposTelefonos RepositorioTiposTelefonos
        {
            get { return new RepositorioTiposTelefonos(); }
        }

        private RepositorioBarrios RepositorioBarrios
        {
            get { return new RepositorioBarrios(); }
        }

        private RepositorioUsuarios RepositorioUsuarios
        {
            get { return new RepositorioUsuarios(); }
        }

        private RepositorioPermisos RepositorioPermisos
        {
            get { return new RepositorioPermisos(); }
        }

        private RepositorioRegistros RepositorioRegistros
        {
            get { return new RepositorioRegistros(); }
        }

        private RepositorioTiposFormasPagos RepositorioTiposFormasPagos
        {
            get { return new RepositorioTiposFormasPagos(); }
        }

        private RepositorioConfiguraciones RepositorioConfiguraciones
        {
            get { return new RepositorioConfiguraciones(); }
        }

        #endregion

        #region Metodos

        public void Inicializar()
        {
            var configuracion = RepositorioConfiguraciones.Devolver();
            if (configuracion == null)
                throw new Exception("La configuración no existe");
            vista.ConfiguracionImagen = configuracion.Imagen;
            vista.ListadoTiposFormasPagos = RepositorioTiposFormasPagos.DevolverTodos();
            if (vista.IdProveedor != 0)
            {
                var proveedor = RepositorioProveedores.DevolverPorId(vista.IdProveedor, true);
                if (proveedor == null)
                    throw new Exception("El proveedor no existe");
                vista.IdRubroProveedor = proveedor.Rubro.Id;
                vista.IdTipoIva = proveedor.TipoIva.Id;
                vista.IdListaPrecioCompra = proveedor.ListaPrecioCompra.Id;
                vista.Codigo = proveedor.Codigo;
                vista.Nombre = proveedor.Nombre;
                vista.LimiteDeuda = proveedor.LimiteDeuda;
                vista.Cuit = proveedor.Cuit;
                vista.Email = proveedor.Email;
                vista.SitioWeb = proveedor.SitioWeb;
                vista.Observaciones = proveedor.Observaciones;
                vista.Imagen = proveedor.Imagen;
                vista.ListadoDomicilios = proveedor.Domicilios;
                vista.ListadoTelefonos = proveedor.Telefonos;
                vista.IdTiposFormasPagos = proveedor.TiposFormasPagos.Select(x => x.Id).ToList();
                vista.ListadoCamposPersonalizados = proveedor.CamposPersonalizados;
            }
            else
            {
                vista.ListadoDomicilios = new List<DomicilioProveedor>();
                vista.ListadoTelefonos = new List<TelefonoProveedor>();
                var listadoCamposPersonalizados = new List<ProveedorCampoPersonalizadoProveedor>();
                foreach (var item in RepositorioCamposPersonalizadosProveedores.DevolverTodos())
                    listadoCamposPersonalizados.Add(new ProveedorCampoPersonalizadoProveedor()
                    {
                        Entidad = item,
                        Valor = String.Empty
                    });
                vista.ListadoCamposPersonalizados = listadoCamposPersonalizados;
            }
        }

        public void Aceptar()
        {
            var usuario = RepositorioUsuarios.DevolverPorId(vista.IdUsuarioSistema);
            if (usuario == null)
                throw new Exception("El usuario no existe");
            if (vista.IdProveedor == 0)
            {
                if (!usuario.Perfil.Permisos.Exists(x => x.Id == (Byte)EnumPermisos.ProveedoresAlta))
                    throw new Exception("Permisos insuficientes");
            }
            else if (!usuario.Perfil.Permisos.Exists(x => x.Id == (Byte)EnumPermisos.ProveedoresModificacion))
                throw new Exception("Permisos insuficientes");

            if (String.IsNullOrWhiteSpace(vista.Codigo))
                throw new Exception("El código no puede quedar vacío");
            if (String.IsNullOrWhiteSpace(vista.Nombre))
                throw new Exception("El nombre no puede quedar vacío");
            if (vista.IdRubroProveedor == 0)
                throw new Exception("El rubro de proveedor no puede quedar vacío");
            if (vista.IdTipoIva == 0)
                throw new Exception("El tipo de I.V.A. no puede quedar vacío");
            if (vista.IdListaPrecioCompra == 0)
                throw new Exception("La lista de precios de compra no puede quedar vacía");

            Proveedor proveedor;
            if (vista.IdProveedor != 0)
            {
                proveedor = RepositorioProveedores.DevolverPorId(vista.IdProveedor, true);
                if (proveedor == null)
                    throw new Exception("El proveedor no existe");
            }
            else
                proveedor = new Proveedor();

            var proveedorCodigo = RepositorioProveedores.DevolverPorCodigo(vista.Codigo.Trim());
            if (proveedorCodigo != null)
                if (vista.IdProveedor != 0)
                {
                    if (proveedorCodigo.Id != proveedor.Id)
                        throw new Exception("Ya existe un proveedor con el mismo código");
                }
                else
                    throw new Exception("Ya existe un proveedor con el mismo código");

            proveedor.Rubro = RepositorioRubrosProveedores.DevolverPorId(vista.IdRubroProveedor);
            if (proveedor.Rubro == null)
                throw new Exception("El rubro de proveedor no existe");
            proveedor.TipoIva = RepositorioTiposIvas.DevolverPorId(vista.IdTipoIva);
            if (proveedor.TipoIva == null)
                throw new Exception("El tipo de I.V.A no existe");
            proveedor.ListaPrecioCompra = RepositorioListasPreciosCompras.DevolverPorId(vista.IdListaPrecioCompra);
            if (proveedor.ListaPrecioCompra == null)
                throw new Exception("La lista de precios de compra no existe");

            proveedor.Codigo = vista.Codigo.Trim();
            proveedor.Nombre = vista.Nombre.Trim();

            proveedor.Cuit = vista.Cuit.Trim();
            if (!String.IsNullOrWhiteSpace(proveedor.Cuit))
                if (!Validaciones.ValidarCuit(proveedor.Cuit))
                    throw new Exception("El C.U.I.T. es inválido");

            if (vista.LimiteDeuda < 0)
                throw new Exception("El limite de deuda no puede ser menor a cero");

            proveedor.Email = vista.Email.Trim();
            if (!String.IsNullOrWhiteSpace(proveedor.Email))
                if (!Validaciones.ValidarEmail(proveedor.Email))
                    throw new Exception("El mail es inválido");

            proveedor.SitioWeb = vista.SitioWeb.Trim();
            if (!String.IsNullOrWhiteSpace(proveedor.SitioWeb))
                if (proveedor.SitioWeb.Contains(' '))
                    throw new Exception("El sitio web es inválido");

            proveedor.Observaciones = vista.Observaciones.Trim();
            proveedor.Imagen = vista.Imagen;

            var registro = new Registro();
            registro.Usuario = usuario;
            if (vista.IdProveedor == 0)
                registro.Evento = RepositorioEventos.DevolverPorId((Byte)EnumEventos.ProveedoresAlta);
            else
                registro.Evento = RepositorioEventos.DevolverPorId((Byte)EnumEventos.ProveedoresModificacion);
            if (registro.Evento == null)
                throw new Exception("El evento no existe");

            if (vista.IdProveedor == 0)
                RepositorioProveedores.Insertar(proveedor);
            else
            {
                RepositorioProveedores.Modificar(proveedor);
                RepositorioProveedores.EliminarTiposFormasPagosPorProveedor(proveedor);
                RepositorioProveedores.EliminarDomiciliosPorProveedor(proveedor);
                RepositorioProveedores.EliminarTelefonosPorProveedor(proveedor);
                RepositorioProveedores.EliminarCamposPersonalizadosPorProveedor(proveedor);
            }
            RepositorioRegistros.Insertar(registro, proveedor);

            foreach (var item in vista.ListadoDomicilios)
            {
                item.Barrio = RepositorioBarrios.DevolverPorId(item.Barrio.Id);
                item.Tipo = RepositorioTiposDomicilios.DevolverPorId(item.Tipo.Id);
                if (item.Tipo != null && item.Barrio != null)
                    RepositorioProveedores.InsertarDomicilio(proveedor, item);
            }

            foreach (var item in vista.ListadoTelefonos)
            {
                item.Tipo = RepositorioTiposTelefonos.DevolverPorId(item.Tipo.Id);
                if (item.Tipo != null)
                    RepositorioProveedores.InsertarTelefono(proveedor, item);
            }

            foreach (var item in vista.IdTiposFormasPagos)
            {
                var tipoFomaPago = RepositorioTiposFormasPagos.DevolverPorId(item);
                if (tipoFomaPago != null)
                    RepositorioProveedores.InsertarTipoFormaPago(proveedor, tipoFomaPago);
            }

            foreach (var item in vista.ListadoCamposPersonalizados)
                if (!String.IsNullOrWhiteSpace(item.Valor))
                {
                    item.Entidad = RepositorioCamposPersonalizadosProveedores.DevolverPorId(item.Entidad.Id);
                    if (item.Entidad != null)
                        RepositorioProveedores.InsertarCampoPersonalizado(proveedor, item);
                }
        }

        public void DomicilioAgregar()
        {
            if (String.IsNullOrWhiteSpace(vista.DomicilioCalle))
                throw new Exception("La calle no puede quedar vacía");
            if (String.IsNullOrWhiteSpace(vista.DomicilioNumero))
                throw new Exception("El número no puede quedar vacío");
            if (vista.DomicilioIdTipoDomicilio == 0)
                throw new Exception("El tipo de domicilio no puede quedar vacío");
            if (vista.DomicilioIdBarrio == 0)
                throw new Exception("El barrio no puede quedar vacío");
            var barrio = RepositorioBarrios.DevolverPorId(vista.DomicilioIdBarrio);
            if (barrio == null)
                throw new Exception("El barrio no existe");
            var tipo = RepositorioTiposDomicilios.DevolverPorId(vista.DomicilioIdTipoDomicilio);
            if (tipo == null)
                throw new Exception("El tipo de domicilio no existe");

            var lista = vista.ListadoDomicilios.ToList();
            var contador = 1;
            foreach (var item in lista)
            {
                item.Id = contador;
                contador++;
            }
            var domicilio = new DomicilioProveedor();
            domicilio.Id = contador;
            domicilio.Tipo = tipo;
            domicilio.Barrio = barrio;
            domicilio.Calle = vista.DomicilioCalle.Trim();
            domicilio.Numero = vista.DomicilioNumero.Trim();
            domicilio.Piso = vista.DomicilioPiso.Trim();
            domicilio.Departamento = vista.DomicilioDepartamento.Trim();
            lista.Add(domicilio);
            vista.ListadoDomicilios = lista;
        }

        public void DomicilioQuitar()
        {
            var lista = vista.ListadoDomicilios.ToList();
            lista.Remove(lista.SingleOrDefault(x => x.Id == vista.DomicilioId));
            vista.ListadoDomicilios = lista;
        }

        public void DomicilioEditar()
        {
            if (String.IsNullOrWhiteSpace(vista.DomicilioCalle))
                throw new Exception("La calle no puede quedar vacía");
            if (String.IsNullOrWhiteSpace(vista.DomicilioNumero))
                throw new Exception("El número no puede quedar vacío");
            if (vista.DomicilioIdTipoDomicilio == 0)
                throw new Exception("El tipo de domicilio no puede quedar vacío");
            if (vista.DomicilioIdBarrio == 0)
                throw new Exception("El barrio no puede quedar vacío");
            var barrio = RepositorioBarrios.DevolverPorId(vista.DomicilioIdBarrio);
            if (barrio == null)
                throw new Exception("El barrio no existe");
            var tipo = RepositorioTiposDomicilios.DevolverPorId(vista.DomicilioIdTipoDomicilio);
            if (tipo == null)
                throw new Exception("El tipo de domicilio no existe");

            var lista = vista.ListadoDomicilios.ToList();
            foreach (var item in lista)
                if (item.Id == vista.DomicilioId)
                {
                    item.Tipo = tipo;
                    item.Barrio = barrio;
                    item.Calle = vista.DomicilioCalle.Trim();
                    item.Numero = vista.DomicilioNumero.Trim();
                    item.Piso = vista.DomicilioPiso.Trim();
                    item.Departamento = vista.DomicilioDepartamento.Trim();
                }
            vista.ListadoDomicilios = lista;
        }

        public void TelefonoAgregar()
        {
            if (String.IsNullOrWhiteSpace(vista.TelefonoCodigoArea))
                throw new Exception("La código de área no puede quedar vacío");
            if (String.IsNullOrWhiteSpace(vista.TelefonoNumero))
                throw new Exception("El número no puede quedar vacío");
            if (vista.TelefonoIdTipoTelefono == 0)
                throw new Exception("El tipo de teléfono no puede quedar vacío");
            var tipo = RepositorioTiposTelefonos.DevolverPorId(vista.TelefonoIdTipoTelefono);
            if (tipo == null)
                throw new Exception("El tipo de teléfono no existe");

            var lista = vista.ListadoTelefonos.ToList();
            var contador = 1;
            foreach (var item in lista)
            {
                item.Id = contador;
                contador++;
            }
            var telefono = new TelefonoProveedor();
            telefono.Id = contador;
            telefono.Tipo = tipo;
            telefono.CodigoArea = vista.TelefonoCodigoArea.Trim();
            telefono.Numero = vista.TelefonoNumero.Trim();
            lista.Add(telefono);
            vista.ListadoTelefonos = lista;
        }

        public void TelefonoQuitar()
        {
            var lista = vista.ListadoTelefonos.ToList();
            lista.Remove(lista.SingleOrDefault(x => x.Id == vista.TelefonoId));
            vista.ListadoTelefonos = lista;
        }

        public void TelefonoEditar()
        {
            if (String.IsNullOrWhiteSpace(vista.TelefonoCodigoArea))
                throw new Exception("La código de área no puede quedar vacío");
            if (String.IsNullOrWhiteSpace(vista.TelefonoNumero))
                throw new Exception("El número no puede quedar vacío");
            if (vista.TelefonoIdTipoTelefono == 0)
                throw new Exception("El tipo de teléfono no puede quedar vacío");
            var tipo = RepositorioTiposTelefonos.DevolverPorId(vista.TelefonoIdTipoTelefono);
            if (tipo == null)
                throw new Exception("El tipo de teléfono no existe");

            var lista = vista.ListadoTelefonos.ToList();
            foreach (var item in lista)
                if (item.Id == vista.TelefonoId)
                {
                    item.Tipo = tipo;
                    item.CodigoArea = vista.TelefonoCodigoArea.Trim();
                    item.Numero = vista.TelefonoNumero.Trim();
                }
            vista.ListadoTelefonos = lista;
        }

        #endregion
    }
}
